package com.harmontronics.hanma.paas.paas.domain.app.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.harmontronics.hanma.paas.paas.common.PageBase;
import com.harmontronics.hanma.paas.paas.consts.BaseI18nKeyEnum;
import com.harmontronics.hanma.paas.paas.consts.DbConstants;
import com.harmontronics.hanma.paas.paas.consts.NumberEnum;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmCarbonCopy;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmProcess;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmTask;
import com.harmontronics.hanma.paas.paas.domain.app.entity.UserTaskForm;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.BpmnConstant;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.CommentTypeEnum;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.FlowableConstant;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.I18nKeyEnum;
import com.harmontronics.hanma.paas.paas.domain.app.repository.persistence.HmModelRepository;
import com.harmontronics.hanma.paas.paas.domain.app.repository.persistence.HmProcInstReadRepository;
import com.harmontronics.hanma.paas.paas.domain.app.repository.po.HmProcInstReadPO;
import com.harmontronics.hanma.paas.paas.domain.app.service.cmd.AddCcIdentityLinkCmd;
import com.harmontronics.hanma.paas.paas.exception.ErrorKeyException;
import com.harmontronics.hanma.paas.paas.token.ComposeTokenKit;
import com.harmontronics.hanma.paas.paas.utils.FlowableQueryUtils;
import com.harmontronics.hanma.paas.paas.utils.FlowableUtils;
import com.harmontronics.hanma.paas.paas.utils.RequestUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExtensionElement;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.NativeProcessDefinitionQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.identitylink.service.impl.persistence.entity.IdentityLinkEntity;
import org.flowable.task.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ldb
 */
@Service("hmProcessRuntimeService")
@DS("#header.App-Unique")
public class HmProcessRuntimeService {
    @Autowired
    protected HistoryService historyService;
    @Autowired
    HmHttpRequestDefinitionService hmHttpRequestDefinitionService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ManagementService managementService;
    @Autowired
    private HmProcessService hmProcessService;
    @Autowired
    private HmModelRepository hmModelRepository;
    @Autowired
    private HmProcInstReadRepository hmProcInstReadRepository;
    @Autowired
    private ComposeTokenKit composeTokenKit;

    @Transactional(rollbackFor = Exception.class)
    public void start(Long processId, Map<String, Object> values, List<HmCarbonCopy> carbonCopys) {

        HmProcess hmProcess = hmProcessService.findById(processId, false);
        hmProcess.checkActivated();

        Long userId = composeTokenKit.getId();
        Map<String, Object> startVariables = null;
        if (values != null && !values.isEmpty()) {
            startVariables = new HashMap<>(values);
            // 默认设置流程启动人变量 __initiator__
        } else {
            startVariables = new HashMap<>(1);
            // 默认设置流程启动人变量 __initiator__
        }
        String appUnique = RequestUtils.getAppUnique();
        if (!StringUtils.isEmpty(appUnique) && !DbConstants.DS_MASTER_NAME.equals(appUnique)) {
            startVariables.put("appUnique", appUnique.split("_")[1]);
        }
        Long id = hmModelRepository.dynamicInsert(hmProcess.getModelCode(), values);
        startVariables.put(FlowableConstant.MODEL_DATA_ID, id);
        startVariables.put(FlowableConstant.MODEL_CODE, hmProcess.getModelCode());
        startVariables.put(FlowableConstant.INITIATOR, userId);
        Authentication.setAuthenticatedUserId(userId.toString());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(hmProcess.getDeploymentId()).singleResult();

        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
        processInstanceBuilder.processDefinitionId(processDefinition.getId());
        // 流程实例标题
        processInstanceBuilder.name(processDefinition.getName());
        processInstanceBuilder.variables(startVariables);
        ProcessInstance instance = processInstanceBuilder.start();
        String processInstanceId = instance.getProcessInstanceId();
        //更新流程实例数据到model
        Map<String, Object> params = new HashMap<>();
        params.put("process_id", processId);
        params.put("process_instance_id", processInstanceId);
        params.put(DbConstants.ID, id);
        hmModelRepository.dynamicUpdate(hmProcess.getModelCode(), params);
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        for (Task task : tasks) {
            // 约定：发起者节点为 __initiator__ ,则自动完成任务
            if (FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey())) {
                addComment(task.getId(), processInstanceId, userId.toString(), CommentTypeEnum.TJ, null);
                if (StringUtils.isEmpty(task.getAssignee())) {
                    taskService.setAssignee(task.getId(), userId.toString());
                }

                taskService.complete(task.getId());


                if (!CollectionUtils.isEmpty(carbonCopys)) {
                    managementService.executeCommand(new AddCcIdentityLinkCmd(processInstanceId, task.getId(), userId.toString()
                            , carbonCopys));
                }
            }
        }
    }

    public void addComment(String taskId, String processInstanceId, String userId, CommentTypeEnum type,
                           String message) {
        Authentication.setAuthenticatedUserId(userId);
        type = type == null ? CommentTypeEnum.SP : type;
        message = (message == null || message.length() == 0) ? type.getName() : message;
        taskService.addComment(taskId, processInstanceId, type.toString(), message);
    }

    @Transactional(rollbackFor = Exception.class)
    public void completeTask(Long processId,String processInstanceId,String taskId, String message, Map<String, Object> values, List<HmCarbonCopy> carbonCopys, String modelKey, String serviceKey, TransUserIdFunction function) throws SQLException, IOException {

        //启动流程
        if(processInstanceId ==null){
            hmHttpRequestDefinitionService.execute(modelKey, null, serviceKey, values, null, null, null);
            start(processId,values,carbonCopys);
            return;
        }
        Long userId = composeTokenKit.getId();
        String currUserId = userId.toString();

        Task task = getTaskNotNull(taskId);
        List<Long> userIds = function.doTrans(task.getAssignee());
        if (!userIds.contains(userId)) {
            throw new ErrorKeyException(BaseI18nKeyEnum.NO_PERMISSION);
        }

        hmHttpRequestDefinitionService.execute(modelKey, null, serviceKey, values, null, null, null);

        taskService.setAssignee(taskId, currUserId);
        Map<String, Object> completeVariables = null;
        if (values != null && !values.isEmpty()) {
            completeVariables = new HashMap<>(values);
            // 非会签用户节点，默认设置流程变量 __taskDefinitionKey__=currUserId，用于存储该节点执行人，且以最近的执行人为准
            UserTask userTask = (UserTask) FlowableUtils.getFlowElement(repositoryService,
                    task.getProcessDefinitionId(), task.getTaskDefinitionKey());
            if (userTask != null && !userTask.hasMultiInstanceLoopCharacteristics()) {
                completeVariables.put("__" + task.getTaskDefinitionKey() + "__", currUserId);
            }
        } else {
            // 非会签用户节点，默认设置流程变量 __taskDefinitionKey__=currUserId，用于存储该节点执行人，且以最近的执行人为准
            UserTask userTask = (UserTask) FlowableUtils.getFlowElement(repositoryService,
                    task.getProcessDefinitionId(), task.getTaskDefinitionKey());
            if (userTask != null && !userTask.hasMultiInstanceLoopCharacteristics()) {
                completeVariables = new HashMap<>(1);
                completeVariables.put("__" + task.getTaskDefinitionKey() + "__", currUserId);
            }
        }
        this.addComment(taskId, task.getProcessInstanceId(), currUserId,
                FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey()) ? CommentTypeEnum.CXTJ :
                        CommentTypeEnum.WC, message);
        // 处理抄送
        if (!CollectionUtils.isEmpty(carbonCopys)) {
            List<HmCarbonCopy> hmCarbonCopies = carbonCopys.stream().filter(e -> !hmProcInstReadRepository.exists(task.getProcessInstanceId(), e.getUserId().toString(), task.getId())).collect(Collectors.toList());
            if (!hmCarbonCopies.isEmpty()) {
                for (HmCarbonCopy hmCarbonCopy : hmCarbonCopies) {
                    HmProcInstReadPO readPO = new HmProcInstReadPO();
                    readPO.setProcInstId(task.getProcessInstanceId());
                    readPO.setUserId(hmCarbonCopy.getUserId().toString());
                    readPO.setRead(NumberEnum.ZERO.getNum());
                    readPO.setTaskId(task.getId());
                    readPO.setCreateDate(LocalDateTime.now());
                    hmProcInstReadRepository.save(readPO);
                }
                managementService.executeCommand(new AddCcIdentityLinkCmd(task.getProcessInstanceId(), task.getId(),
                        currUserId, hmCarbonCopies));
            }
        }
        // 判断是否是协办完成还是正常流转
        if (isTaskPending(task)) {
            taskService.resolveTask(taskId, completeVariables);
            // 如果当前执行人是任务所有人，直接完成任务
            if (currUserId.equals(task.getOwner())) {
                taskService.complete(taskId, completeVariables);
            }
        } else {
            taskService.complete(taskId, completeVariables);
        }
      //  updateModelData(values, task);
    }

    /**
     * 更新数据到对应的模型表中
     *
     * @param values
     * @param task
     */
    private void updateModelData(Map<String, Object> values, Task task) {
        if (CollectionUtils.isEmpty(values)) {
            return;
        }
        values.remove(FlowableConstant.PROCESS_INSTANCE_FORM_DATA);
        if (values.isEmpty()) {
            return;
        }
        Map<String, Object> processVariables = task.getProcessVariables();
        Object idObj = processVariables.get(FlowableConstant.MODEL_DATA_ID);
        Object modelCodeObj = processVariables.get(FlowableConstant.MODEL_CODE);
        if (idObj == null) {
            return;
        }
        values.put(DbConstants.ID, idObj);
        hmModelRepository.dynamicUpdate(modelCodeObj.toString(), values);
    }

    public Task getTaskNotNull(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new ErrorKeyException(I18nKeyEnum.TASK_NOT_FOUND);
        }
        return task;
    }

    public boolean isTaskOwnerOrAssignee(String currentUser, Task task) {
        return currentUser.equals(task.getOwner()) || currentUser.equals(task.getAssignee());
    }

    public boolean isTaskPending(Task task) {
        return DelegationState.PENDING.equals(task.getDelegationState());
    }

    public boolean validateIfUserIsInitiatorAndCanCompleteTask(String userId, TaskInfo task) {
        boolean canCompleteTask = false;
        if (task.getProcessInstanceId() != null) {
            HistoricProcessInstance historicProcessInstance =
                    historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            if (historicProcessInstance != null && org.apache.commons.lang3.StringUtils.isNotEmpty(historicProcessInstance.getStartUserId())) {
                String processInstanceStartUserId = historicProcessInstance.getStartUserId();
                if (userId.equals(processInstanceStartUserId) && validateIfInitiatorCanCompleteTask(task)) {
                    return true;
                }
            }

        }
        return canCompleteTask;
    }

    public boolean validateIfInitiatorCanCompleteTask(TaskInfo task) {
        boolean canCompleteTask = false;
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        if (flowElement instanceof UserTask) {
            UserTask userTask = (UserTask) flowElement;
            List<ExtensionElement> extensionElements = userTask.getExtensionElements().get("initiator-can-complete");
            if (extensionElements != null && !extensionElements.isEmpty()) {
                String value = extensionElements.get(0).getElementText();
                if (!StringUtils.isEmpty(value) && Boolean.parseBoolean(value)) {
                    canCompleteTask = true;
                }
            }
        }

        return canCompleteTask;
    }

    public PageBase<HmTask> listToDo(Long processId, List<String> assigneeList, int pageNo, int pageSize) {

        Long userId = composeTokenKit.getId();
        ProcessDefinition processDefinition = hmProcessService.getProcessDefinition(processId);
        StringJoiner joiner = new StringJoiner(",");
        assigneeList.forEach(e -> joiner.add("'" + e + "'"));

        NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
        nativeTaskQuery.sql("SELECT T.ID_,T.NAME_,T.CREATE_TIME_,I.USER_ID_ OWNER_,T.PROC_DEF_ID_  FROM " + managementService.getTableName(Task.class) + " T INNER JOIN " +
                managementService.getTableName(IdentityLinkEntity.class) + " I ON I.PROC_INST_ID_ = T.PROC_INST_ID_ WHERE T.OWNER_ IN ("+joiner.toString()+") OR T.ASSIGNEE_ IN ("+joiner.toString()+") AND I.TYPE_=#{type} AND I.TASK_ID_ IS NULL" +
                (processDefinition == null ? "" : " AND T.PROC_DEF_ID_=#{procDefId}"))
                .parameter("type", IdentityLinkType.STARTER);
        if (processDefinition != null) {
            nativeTaskQuery.parameter("procDefId", processDefinition.getId());
        }
        NativeTaskQuery countNativeTaskQuery = taskService.createNativeTaskQuery();
        countNativeTaskQuery.sql("SELECT COUNT(*)  FROM " + managementService.getTableName(Task.class) + " T INNER JOIN " +
                managementService.getTableName(IdentityLinkEntity.class) + " I ON I.PROC_INST_ID_ = T.PROC_INST_ID_ WHERE T.OWNER_ IN ("+joiner.toString()+") OR T.ASSIGNEE_ IN ("+joiner.toString()+") AND I.TYPE_=#{type} AND I.TASK_ID_ IS NULL" +
                (processDefinition == null ? "" : " AND T.PROC_DEF_ID_=#{procDefId}"))
                .parameter("type", IdentityLinkType.STARTER).parameter("userId", userId.toString());
        if (processDefinition != null) {
            countNativeTaskQuery.parameter("procDefId", processDefinition.getId());
        }
        PageBase<Task> pageBase = FlowableQueryUtils.doTaskQuery(nativeTaskQuery, countNativeTaskQuery, pageNo, pageSize);
        PageBase<HmTask> resultPageBase = new PageBase<HmTask>().copy(pageBase);
        if (pageBase.isEmpty()) {
            return resultPageBase;
        }
        List<HmTask> dataList = new ArrayList<>();
        List<ProcessDefinition> processDefinitions = getProcessDefinitions(processDefinition, pageBase.getData());
        for (Task task : pageBase.getData()) {
            HmTask hmTask = new HmTask();
            hmTask.setTaskId(task.getId());
            hmTask.setTaskName(task.getName());
            hmTask.setCreateTime(task.getCreateTime());
            hmTask.setSubmitterId(task.getOwner());
            for (ProcessDefinition definition : processDefinitions) {
                if (definition.getId().equals(task.getProcessDefinitionId())) {
                    hmTask.setProcessName(definition.getName());
                }
            }
            dataList.add(hmTask);

        }


        resultPageBase.setData(dataList);
        return resultPageBase;

    }


    public List<HmProcess> getOnGoingProcess(List<String> assigneeList) {
        StringJoiner joiner = new StringJoiner(",");
        assigneeList.forEach(e -> joiner.add("'" + e + "'"));
        NativeProcessDefinitionQuery query = repositoryService.createNativeProcessDefinitionQuery();
        query.sql("SELECT ID_,DEPLOYMENT_ID_,CATEGORY_ FROM " + managementService.getTableName(ProcessDefinition.class) + " WHERE ID_ IN " +
                "(SELECT DISTINCT PROC_DEF_ID_ FROM " + managementService.getTableName(Task.class) + " WHERE ASSIGNEE_ IN (" + joiner.toString() + "))"
        );
        List<ProcessDefinition> processDefinitions = query.list();
        if (CollectionUtils.isEmpty(processDefinitions)) {
            return new ArrayList<>();
        }
        List<String> deploymentIds = processDefinitions.stream().map(ProcessDefinition::getDeploymentId).collect(Collectors.toList());
        return hmProcessService.findByDeploymentIdIn(deploymentIds);
    }

    public List<HmProcess> getMyStartProcess() {
        Long userId = composeTokenKit.getId();


        //历史流程记录
        NativeProcessDefinitionQuery nativeProcessDefinitionQuery = repositoryService.createNativeProcessDefinitionQuery();
        nativeProcessDefinitionQuery.sql("SELECT ID_,DEPLOYMENT_ID_,CATEGORY_ FROM " + managementService.getTableName(ProcessDefinition.class) + " WHERE ID_ IN( SELECT DISTINCT PROC_DEF_ID_ FROM " + managementService.getTableName(HistoricProcessInstance.class) + " WHERE " +
                "START_USER_ID_=#{userId})").parameter("userId", userId.toString());
        List<ProcessDefinition> processDefinitions = nativeProcessDefinitionQuery.list();

        List<String> deploymentIds = processDefinitions.stream().map(ProcessDefinition::getDeploymentId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(deploymentIds)) {
            return new ArrayList<>();
        }
        return hmProcessService.findByDeploymentIdIn(deploymentIds);
    }

    public UserTaskForm getTaskFormId(String taskId) {
        TaskQuery taskQuery = taskService.createTaskQuery().taskId(taskId).includeProcessVariables();

        Task task = taskQuery.singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        org.flowable.bpmn.model.Process process = bpmnModel.getMainProcess();
        Collection<FlowElement> flowElements = process.getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if (!(flowElement instanceof UserTask)) {
                continue;
            }
            UserTask userTask = (UserTask) flowElement;
            if (!userTask.getId().equals(task.getTaskDefinitionKey())) {
                continue;
            }
            Map<String, List<ExtensionElement>> extensionElementMap = userTask.getExtensionElements();
            List<ExtensionElement> fieldElements = extensionElementMap.get(BpmnConstant.FIELD);
            UserTaskForm userTaskForm = new UserTaskForm();
            String formKey = userTask.getFormKey();
            userTaskForm.setTodo(formKey.replace(".form", ""));
            for (ExtensionElement extensionElement : fieldElements) {
                if (!extensionElement.getName().equals(BpmnConstant.FIELD)) {
                    continue;
                }
                String value = extensionElement.getAttributeValue(null, BpmnConstant.NAME);
                if ("formView".equals(value)) {
                    String formId = FlowableUtils.getStringExtensionElementValue(extensionElement);
                    userTaskForm.setView(formId);
                }
                if ("formNotice".equals(value)) {
                    String formId = FlowableUtils.getStringExtensionElementValue(extensionElement);
                    userTaskForm.setNotice(formId);
                }
                if ("buttons".equals(value)) {
                    String buttonsJson = FlowableUtils.getStringExtensionElementValue(extensionElement);
                    userTaskForm.setButtons(buttonsJson);
                }
            }

            Object idObj = task.getProcessVariables().get(FlowableConstant.MODEL_DATA_ID);
            if (idObj != null) {
                userTaskForm.setDataId(Long.parseLong(idObj.toString()));
            }
            return userTaskForm;

        }
        return null;
    }

    public PageBase<HmTask> listMyStartProcessToDo(Long processId, int pageNo, int pageSize) {
        Long userId = composeTokenKit.getId();
        ProcessDefinition processDefinition = hmProcessService.getProcessDefinition(processId);


        NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
        nativeTaskQuery.sql("SELECT T.ID_,T.NAME_,T.CREATE_TIME_,T.ASSIGNEE_,T.PROC_DEF_ID_  FROM " + managementService.getTableName(Task.class) + " T INNER JOIN " +
                managementService.getTableName(IdentityLinkEntity.class) + " I ON I.PROC_INST_ID_ = T.PROC_INST_ID_ WHERE I.USER_ID_=#{userId} AND I.TYPE_=#{type} AND I.TASK_ID_ IS NULL" +
                (processDefinition == null ? "" : " AND T.PROC_DEF_ID_=#{procDefId}"))
                .parameter("type", IdentityLinkType.STARTER).parameter("userId", userId.toString());
        if (processDefinition != null) {
            nativeTaskQuery.parameter("procDefId", processDefinition.getId());
        }
        NativeTaskQuery countNativeTaskQuery = taskService.createNativeTaskQuery();
        countNativeTaskQuery.sql("SELECT COUNT(*)  FROM " + managementService.getTableName(Task.class) + " T INNER JOIN " +
                managementService.getTableName(IdentityLinkEntity.class) + " I ON I.PROC_INST_ID_ = T.PROC_INST_ID_ WHERE I.USER_ID_=#{userId} AND I.TYPE_=#{type} AND I.TASK_ID_ IS NULL" +
                (processDefinition == null ? "" : " AND T.PROC_DEF_ID_=#{procDefId}"))
                .parameter("type", IdentityLinkType.STARTER).parameter("userId", userId.toString());
        if (processDefinition != null) {
            countNativeTaskQuery.parameter("procDefId", processDefinition.getId());
        }
        PageBase<Task> pageBase = FlowableQueryUtils.doTaskQuery(nativeTaskQuery, countNativeTaskQuery, pageNo, pageSize);
        PageBase<HmTask> resultPageBase = new PageBase<HmTask>().copy(pageBase);
        if (pageBase.isEmpty()) {
            return resultPageBase;
        }
        List<HmTask> dataList = new ArrayList<>();
        List<ProcessDefinition> processDefinitions = getProcessDefinitions(processDefinition, pageBase.getData());
        for (Task task : pageBase.getData()) {
            HmTask hmTask = new HmTask();
            hmTask.setTaskId(task.getId());
            hmTask.setTaskName(task.getName());
            hmTask.setCreateTime(task.getCreateTime());
            hmTask.setSubmitterId(task.getAssignee());
            for (ProcessDefinition definition : processDefinitions) {
                if (definition.getId().equals(task.getProcessDefinitionId())) {
                    hmTask.setProcessName(definition.getName());
                }
            }
            dataList.add(hmTask);
        }
        resultPageBase.setData(dataList);
        return resultPageBase;
    }

    public List<ProcessDefinition> getProcessDefinitions(ProcessDefinition processDefinition, List<? extends TaskInfo> taskInfos) {
        List<ProcessDefinition> processDefinitions;
        if (processDefinition != null) {
            processDefinitions = CollUtil.toList(processDefinition);
        } else {
            List<String> procDefIdList = taskInfos.stream().map(TaskInfo::getProcessDefinitionId).collect(Collectors.toList());
            processDefinitions = repositoryService.createProcessDefinitionQuery().processDefinitionIds(new HashSet<>(procDefIdList)).list();
        }
        return processDefinitions;
    }


    public PageBase<HmTask> listMyStartProcessFinish(Long processId, int pageNo, int pageSize) {
        Long userId = composeTokenKit.getId();

        ProcessDefinition processDefinition = hmProcessService.getProcessDefinition(processId);
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().finished().startedBy(userId.toString());
        if (processDefinition != null) {
            query.processDefinitionId(processDefinition.getId());
        }
        PageBase<HistoricProcessInstance> pageBase = FlowableQueryUtils.doQuery(query, pageNo, pageSize);
        PageBase<HmTask> resultPageBase = new PageBase<HmTask>().copy(pageBase);
        if (pageBase.isEmpty()) {
            return resultPageBase;
        }
        List<HmTask> dataList = new ArrayList<>();
        for (HistoricProcessInstance historicProcessInstance : pageBase.getData()) {
            HmTask hmTask = new HmTask();
            hmTask.setProcessName(historicProcessInstance.getName());
            hmTask.setCreateTime(historicProcessInstance.getStartTime());
            hmTask.setEndTime(historicProcessInstance.getEndTime());
            dataList.add(hmTask);
        }
        resultPageBase.setData(dataList);
        return resultPageBase;
    }

    public void triggerReceiveTask() {
        ProcessInstance pi = runtimeService.startProcessInstanceByKey("receiveTask");
        Execution execution = runtimeService.createExecutionQuery()
                .processInstanceId(pi.getId())
                .activityId("waitState")
                .singleResult();


        runtimeService.trigger(execution.getId());
    }
}
